package wiring

import akka.stream.Materializer
import back.wiring.BackAppComponents
import play.api.ApplicationLoader.Context
import play.api._
import com.softwaremill.macwire._
import play.api.db.slick.{ DefaultSlickApi, SlickApi }
import play.api.inject.ApplicationLifecycle
import play.api.libs.ws.ahc.AhcWSComponents
import play.api.mvc.EssentialFilter
import router.Routes
import play.filters.HttpFiltersComponents
import play.filters.csrf.CSRFFilter
import teacher.wiring.AssetsAppComponents
import utils.{ ArcherNamedDatabaseConfigProvider, CommonDB }

import scala.concurrent.ExecutionContext

trait PlayCommonWiring {
  self =>

  protected val environment: Environment
  protected val configuration: Configuration
  protected val lifecycle: ApplicationLifecycle
  protected implicit val executionContext: ExecutionContext

  protected lazy val DefaultSlickApi: SlickApi = wire[DefaultSlickApi]

  protected lazy val ArcherNamedDatabaseConfigProvider =
    wire[ArcherNamedDatabaseConfigProvider]

  lazy val commonDB: CommonDB = wire[CommonDB]

}

class PlayCommonWiringImpl(
  protected override val environment: Environment,
  protected override val configuration: Configuration,
  protected override val lifecycle: ApplicationLifecycle)(
  implicit
  protected override val executionContext: ExecutionContext)
  extends PlayCommonWiring

//not to use
class InjectedAhcWSComponents1111(
  override val environment: Environment,
  override val configuration: Configuration,
  override val applicationLifecycle: ApplicationLifecycle,
  override val materializer: Materializer,
  override val executionContext: ExecutionContext)
  extends AhcWSComponents

class AppComponents(context: Context)
  extends BuiltInComponentsFromContext(context)
  with HttpFiltersComponents {
  self =>

  //private lazy val ipFilter = wire[IpFilter]

  override def httpFilters: Seq[EssentialFilter] = {
    super.httpFilters.filterNot(_.getClass == classOf[CSRFFilter])
  }

  private implicit val ec = executionContext

  private implicit val Index = wire[archer.parent.controllers.Index]

  private lazy val InjectedAhcWSComponents1111: InjectedAhcWSComponents1111 =
    wire[InjectedAhcWSComponents1111]
  private lazy val wsClient = InjectedAhcWSComponents1111.wsClient

  /*
   * Assets 模块配置开始
   */
  private lazy val AssetsConfiguration: _root_.controllers.AssetsConfiguration =
    wire[_root_.controllers.AssetsConfigurationProvider].get
  private lazy val AssetsMetadata: _root_.controllers.AssetsMetadata =
    wire[_root_.controllers.AssetsMetadataProvider].get
  private lazy val Assets = wire[_root_.controllers.Assets]
  private lazy val archerAssets = wire[archer.controllers.Assets]
  /*
   * Assets 模块配置结束
   */

  /*
   * 数据库模块配置开始
   */
  private lazy val commonWiredIn: PlayCommonWiringImpl =
    wire[PlayCommonWiringImpl]
  private lazy val commonDB = commonWiredIn.commonDB
  /*
   * 数据库模块配置结束
   */

  //Router
  override lazy val router = {
    val routePrefix: String = "/"
    lazy val teacherRoutes = wire[AssetsAppComponents].router
    lazy val backRoutes = wire[BackAppComponents].router
    wire[Routes]
  }

}
